package de.schoar.nagroid.nagios.parser;




import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import de.schoar.android.helper.http.HTTPDownloader;
import de.schoar.android.helper.http.HTTPDownloaderException;
import de.schoar.nagroid.nagios.NagiosHost;
import de.schoar.nagroid.nagios.NagiosService;
import de.schoar.nagroid.nagios.NagiosSite;
import de.schoar.nagroid.nagios.NagiosState;

import net.htmlparser.jericho.*;

public class NagiosV3Parser extends NagiosParser{

	private static final String LOGT = "NagiosV3Parser";

	public NagiosV3Parser(NagiosSite site) {
		super(site);
	}

	@Override
	public void updateProblems() throws NagiosParsingFailedException {
		mNagiosSite.getHosts().clear();
		String url;
		String style = mNagiosSite.getUnhandledOnly() ? "uprobs" : "aprobs";
		url = mNagiosSite.getUrlBase() + "/status.cgi?host=all&servicestatustypes=28&sorttype=2&sortoption=3" + style;
		String user = mNagiosSite.getUrlUser();
		String pass = mNagiosSite.getUrlPass();

		InputStream is;

		try {
			is = new HTTPDownloader(url, user, pass).getBodyAsInputStream();
		} catch (HTTPDownloaderException e) {
			throw new NagiosParsingFailedException(e.getMessage(), e);
		}

		try {
			Source source = new Source(is);
			String line,duration;
			String host = null, nameservice = null;
			/* create a new List with all elements which contains <TD...> tag */
			List<Element> elementList = source.getAllElements("TD");
			Iterator<Element> it = elementList.iterator();
			while(it.hasNext()){
				Element e = (Element)it.next();
				line = e.toString();
				if(isHostDown(line)){
					if (!(e.getContent().getTextExtractor().toString().trim().equalsIgnoreCase(host))){
						host = e.getContent().getTextExtractor().toString().trim();
						mNagiosSite.addHostLast(new NagiosHost(host, NagiosState.HOST_DOWN));
					}
				}
				else {
					if(isHost(line)){
						if (!(e.getContent().getTextExtractor().toString().trim().equalsIgnoreCase(host))){
							host = e.getContent().getTextExtractor().toString().trim();
							mNagiosSite.addHostLast(new NagiosHost(host, NagiosState.HOST_UP));
						}
					}

					else {
						if (isService(line)){
							nameservice = e.getContent().getTextExtractor().toString();
							if(!(mNagiosSite.getHosts().getLast().found_service(nameservice))){
								mNagiosSite.getHosts().getLast().addChild(new NagiosService(nameservice));
							}
						}
						else {
							if(isCriticalDuration(line)){
								duration = e.getContent().getTextExtractor().toString();
								mNagiosSite.getHosts().getLast().getServices().getLast().setMduration(cleanDuration(duration));
								mNagiosSite.getHosts().getLast().getServices().getLast().setmState(NagiosState.SERVICE_CRITICAL);
								if(isAcknowledged(line))mNagiosSite.getHosts().getLast().setAck(true);
							}
							else{
								if(isUnknownDuration(line)){
									duration = e.getContent().getTextExtractor().toString();
									mNagiosSite.getHosts().getLast().getServices().getLast().setMduration(cleanDuration(duration));
									mNagiosSite.getHosts().getLast().getServices().getLast().setmState(NagiosState.SERVICE_UNKNOWN);
									if(isAcknowledged(line))mNagiosSite.getHosts().getLast().setAck(true);

								}
								else{
									if(isWarningDuration(line)){
										duration = e.getContent().getTextExtractor().toString();
										mNagiosSite.getHosts().getLast().getServices().getLast().setMduration(cleanDuration(duration));
										mNagiosSite.getHosts().getLast().getServices().getLast().setmState(NagiosState.SERVICE_WARNING);
										if(isAcknowledged(line))mNagiosSite.getHosts().getLast().setAck(true);

									}
								}

							}
						}
					}
				}

			}
			mNagiosSite.regroup();
		} catch (Exception e) {
			throw new NagiosParsingFailedException(e.getMessage(), e);
		}
	}

	/* return true if the string contains a duration, and if it's a critical state */
	boolean isCriticalDuration(String s){
		if((s.contains("TD CLASS='statusBGCRITICAL' nowrap")
				||s.contains("TD CLASS='statusBGCRITICALACK' nowrap"))
				&&!s.contains(":")){
			return true;
		}
		return false;
	}

	/* return true if the string contains a duration, and if it's a unknown state */
	boolean isUnknownDuration(String s){
		if((s.contains("TD CLASS='statusBGUNKNOWN' nowrap")
				||s.contains("TD CLASS='statusBGUNKNOWNACK' nowrap"))
				&&!s.contains(":")){
			return true;
		}
		return false;
	}


	/* return true if the string contains a duration, and if it's a warning state */
	boolean isWarningDuration(String s){
		if((s.contains("TD CLASS='statusBGWARNING' nowrap")
				||s.contains("TD CLASS='statusBGWARNINGACK' nowrap"))
				&&!s.contains(":")){
			return true;
		}
		return false;
	}


	/* return true if the string contains the name of a UP host */
	boolean isHost(String s){
		if ((s.contains("TD align=left valign=center CLASS='status")) && (s.contains("title="))) return true;
		else if((s.contains("TD CLASS='statusEven' valign=center align=left")) && (s.contains("title=")))return true;
		else if((s.contains("TD CLASS='statusOdd' valign=center align=left")) && (s.contains("title=")))return true;
		else return false;
	}

	/* return true if the string contains the name of a DOWN host */
	boolean isHostDown(String s){
		if(s.contains("CLASS='statusHOSTDOWN'")) {
			System.out.println(s);
			return true;
		}

		return false;
	}

	/* return true if the string contains the name of a service */
	boolean isService(String s){
		if ((s.contains("TD align=left valign=center CLASS='status")) && !(s.contains("title="))) return true;
		else if((s.contains("TD CLASS='statusEven' valign=center align=left")) && !(s.contains("title=")))return true;
		else if((s.contains("TD CLASS='statusOdd' valign=center align=left")) && !(s.contains("title=")))return true;
		else if((s.contains("TD ALIGN=LEFT valign=center CLASS='statusBG")) && !(s.contains("title=")))return true;
		else return false;
	}
	
	boolean isAcknowledged(String s){
		if(s.contains("ACK")) return true;
		else return false;
	}

	/* get number of days, hours, minutes and seconds
	 * and return a new string without seconds or element equals to 0.
	 * keep seconds if other elements equals to 0 */
	String cleanDuration(String s){
		String day,hour,min,sec;
		day = s.substring(0, s.indexOf('d')).trim();
		hour = s.substring(s.indexOf('d')+1, s.indexOf('h')).trim();
		min = s.substring(s.indexOf('h')+1, s.indexOf('m')).trim();
		sec = s.substring(s.indexOf('m')+1, s.indexOf('s')).trim();

		if(day.equalsIgnoreCase("0")){
			if(hour.equalsIgnoreCase("0")){
				if(min.equalsIgnoreCase("0")){
					return (sec + "sec");
				}
				else return (min + "min");
			}
			else return (hour +"h " + min +"min");
		}
		else return (day + "d " + hour + "h " + min + "min");
	}

}
